Blockly.Blocks.function_import = {
  init: function () {
    this.setHelpUrl()
    this.setColour(230)
    this.itemCount_ = 3
    this.updateShape_()
    this.setPreviousStatement(true, null)
    this.setNextStatement(true, null)
    this.setMutator(new Blockly.Mutator(['import_create_with_item']))
    this.setTooltip('function_import')
  },

  mutationToDom: function () {
    const containerBody = Blockly.utils.xml.createElement('mutation')
    containerBody.setAttribute('items', this.itemCount_)
    return containerBody
  },

  updateShape_: function () {
    if (this.itemCount_ && this.getInput('EMPTY')) {
      this.removeInput('EMPTY')
    } else if (!this.itemCount_ && !this.getInput('EMPTY')) {
      this.appendDummyInput('EMPTY').appendField('import')
    }
    // Add new inputs.
    for (let p = 0; p < this.itemCount_; p++) {
      if (!this.getInput('ADD' + p)) {
        const input = this.appendValueInput('ADD' + p).setAlign(
          Blockly.ALIGN_RIGHT
        )
        if (p === 0) {
          input.appendField('import libraries')
        }
      }
    }
    let replaceElement = this.itemCount_
    while (this.getInput('ADD' + replaceElement)) {
      this.removeInput('ADD' + replaceElement)
      replaceElement++
    }
  },

  domToMutation: function (xml) {
    this.itemCount_ = parseInt(xml.getAttribute('items'), 10)
    this.updateShape_()
  },

  compose: function (containerBlock) {
    let itemBlockContent = containerBlock.getInputTargetBlock('STACK')
    const connectionArray = []
    while (itemBlockContent && !itemBlockContent.isInsertionMarker()) {
      connectionArray.push(itemBlockContent.valueConnection_)
      itemBlockContent =
        itemBlockContent.nextConnection && itemBlockContent.nextConnection.targetBlock()
    }
    let i = 0
    while (i < this.itemCount_) {
      const connection = this.getInput('ADD' + i).connection.targetConnection
      if (connection && connectionArray.indexOf(connection) === -1) {
        connection.disconnect()
      }
      i++
    }
    this.itemCount_ = connectionArray.length
    this.updateShape_()
    let j = 0
    while (j < this.itemCount_) {
      Blockly.Mutator.reconnect(connectionArray[j], this, 'ADD' + j)
      j++
    }
  },
  decompose: function (workspace) {
    const containerNewBlock = workspace.newBlock('import_create_with_container')
    containerNewBlock.initSvg()
    let connection = containerNewBlock.getInput('STACK').connection
    for (let i = 0; i < this.itemCount_; i++) {
      const itemBlock = workspace.newBlock('import_create_with_item')
      itemBlock.initSvg()
      connection.connect(itemBlock.previousConnection)
      connection = itemBlock.nextConnection
    }
    return containerNewBlock
  },

  saveConnections: function (containerBlock) {
    let itemBlockTarget = containerBlock.getInputTargetBlock('STACK')
    let i = 0
    while (itemBlockTarget) {
      const inputs = this.getInput('ADD' + i)
      itemBlockTarget.valueConnection_ = inputs && inputs.connection.targetConnection
      i++
      itemBlockTarget =
        itemBlockTarget.nextConnection && itemBlockTarget.nextConnection.targetBlock()
    }
  }
}

Blockly.Blocks.import_create_with_container = {
  init: function () {
    this.setStyle('list_blocks')
    this.appendDummyInput().appendField('add argument')
    this.appendStatementInput('STACK')
    this.setTooltip('add argument')
    this.contextMenu = false
  }
}

Blockly.Blocks.import_create_with_item = {
  init: function () {
    this.setStyle('list_blocks')
    this.appendDummyInput().appendField('argument')
    this.setPreviousStatement(true)
    this.setNextStatement(true)
    this.setTooltip('lambda')
    this.contextMenu = false
    this.setColour(230)
  }
}

Blockly.Python.function_import = function (block) {
  const elements = new Array(block.itemCount_)
  for (let i = 0; i < block.itemCount_; i++) {
    elements[i] =
      Blockly.Python.valueToCode(block, 'ADD' + i, Blockly.Python.ORDER_NONE) ||
      'None'
  }
  const code = 'import ' + elements.join(', ') + '\n'
  return code
}

Blockly.Blocks.as_key = {
  init: function () {
    this.appendValueInput('leftValue').setCheck(null)
    this.appendDummyInput().appendField('as')
    this.appendValueInput('rightValue').setCheck(null)
    this.setInputsInline(true)
    this.setOutput(true, null)
    this.setColour(230)
    this.setTooltip('')
    this.setHelpUrl('')
  }
}

Blockly.Python.as_key = function (block) {
  const leftValue = Blockly.Python.valueToCode(
    block,
    'leftValue',
    Blockly.Python.ORDER_NONE
  )
  const rightValue = Blockly.Python.valueToCode(
    block,
    'rightValue',
    Blockly.Python.ORDER_NONE
  )
  const code = leftValue + ' as ' + rightValue
  return [code, Blockly.Python.ORDER_NONE]
}

Blockly.Blocks.function_import_from = {
  init: function () {
    this.appendValueInput('from').appendField('from')
    this.setHelpUrl()
    this.setColour(230)
    this.itemCount_ = 3
    this.updateShape_()
    this.setPreviousStatement(true, null)
    this.setNextStatement(true, null)
    this.setMutator(new Blockly.Mutator(['import_create_with_item']))
    this.setTooltip('function_import_from')
  },
  updateShape_: function () {
    if (this.itemCount_ && this.getInput('EMPTY')) {
      this.removeInput('EMPTY')
    } else if (!this.itemCount_ && !this.getInput('EMPTY')) {
      this.appendDummyInput('EMPTY').appendField('import')
    }
    // Add new inputs.
    while (index < this.itemCount_) {
      if (!this.getInput('ADD' + index)) {
        const input = this.appendValueInput('ADD' + index).setAlign(
          Blockly.ALIGN_RIGHT
        )
        if (index === 0) {
          input.appendField('import libraries')
        }
      }
      index++
    }
    let replacements = this.itemCount_
    while (this.getInput('ADD' + replacements)) {
      this.removeInput('ADD' + replacements)
      replacements++
    }
  },

  mutationToDom: function () {
    const containerXml = Blockly.utils.xml.createElement('mutation')
    containerXml.setAttribute('items', this.itemCount_)
    return containerXml
  },

  domToMutation: function (xmlElements) {
    this.itemCount_ = parseInt(xmlElements.getAttribute('items'), 10)
    this.updateShape_()
  },

  compose: function (containerBlock) {
    let itemBlockElement = containerBlock.getInputTargetBlock('STACK')
    const connectionsList = []
    while (itemBlockElement && !itemBlockElement.isInsertionMarker()) {
      connectionsList.push(itemBlockElement.valueConnection_)
      itemBlockElement =
        itemBlockElement.nextConnection && itemBlockElement.nextConnection.targetBlock()
    }
    let i = 0
    while (i < this.itemCount_) {
      const connection = this.getInput('ADD' + i).connection.targetConnection
      if (connection && connectionsList.indexOf(connection) === -1) {
        connection.disconnect()
      }
      i++
    }
    this.itemCount_ = connectionsList.length
    this.updateShape_()
    let j = 0
    while (j < this.itemCount_) {
      Blockly.Mutator.reconnect(connectionsList[j], this, 'ADD' + j)
      j++
    }
  },
  decompose: function (workspace) {
    const containerBlockInit = workspace.newBlock('import_create_with_container')
    containerBlockInit.initSvg()
    let connection = containerBlockInit.getInput('STACK').connection
    for (let i = 0; i < this.itemCount_; i++) {
      const itemBlock = workspace.newBlock('import_create_with_item')
      itemBlock.initSvg()
      connection.connect(itemBlock.previousConnection)
      connection = itemBlock.nextConnection
    }
    return containerBlockInit
  },

  saveConnections: function (containerBlock) {
    let itemInputBlock = containerBlock.getInputTargetBlock('STACK')
    let i = 0
    while (itemInputBlock) {
      const input = this.getInput('ADD' + i)
      itemInputBlock.valueConnection_ = input && input.connection.targetConnection
      i++
      itemInputBlock =
        itemInputBlock.nextConnection && itemInputBlock.nextConnection.targetBlock()
    }
  }
}

Blockly.Python.function_import_from = function (block) {
  const from = Blockly.Python.valueToCode(
    block,
    'from',
    Blockly.Python.ORDER_NONE
  )
  const elements = new Array(block.itemCount_)
  for (let i = 0; i < block.itemCount_; i++) {
    elements[i] =
      Blockly.Python.valueToCode(block, 'ADD' + i, Blockly.Python.ORDER_NONE) ||
      'None'
  }
  const code = 'from ' + from + ' import ' + elements.join(', ') + '\n'
  return code
}
